package com.atguigu.gulimall.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.nacos.client.utils.StringUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.product.vo.Catelog2Vo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;

import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;

@Slf4j
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

 @Autowired
 private StringRedisTemplate stringRedisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listTree() {
        //拿到所有分类
        List<CategoryEntity> list = this.baseMapper.selectList(null);
        List<CategoryEntity> oneTree = list.stream().filter(c -> c.getParentCid() == 0)
                .map(c -> {
                    c.setChildren(getChildren(c, list));
                    return c;
                })
                .sorted((s1, s2) -> {
                    return s1.getSort() - s2.getSort();
                })
                .collect(Collectors.toList());
        return oneTree;
    }

    @Override
    public void deleteByIds(Long[] catIds) {
        //批量删除
        //TODO 删除前判断有没有下级节点
        List<CategoryEntity> one = this.baseMapper.getOne(catIds);
        if (one != null && one.size() > 0) {
            throw new RuntimeException("有下级节点，不能删除");
        }
        this.baseMapper.deleteBatchIds(Arrays.asList(catIds));
    }

    @Override
    public Long[] getCatelogIds(Long attrGroupId) {
        List<Long> list = new ArrayList<>();
  getparentid(attrGroupId, list);

        Collections.reverse(list);

        return list.toArray(new Long[list.size()]);
    }

    @Cacheable( value = "category",key = "'ww'")
    @Override
    public List<CategoryEntity> getLeve1Category() {
        QueryWrapper<CategoryEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(CategoryEntity::getParentCid,0);
        return this.baseMapper.selectList(qw);
    }

    private static final String GET_GETCATALOG3_KEY="getgetCatalog3";

    @Override
    public Map<String, List<Catelog2Vo>> getgetCatalog3() {
        //先从redis里面获取
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        String json = ops.get(GET_GETCATALOG3_KEY);
        if (StringUtils.isEmpty(json)){
            Map<String, List<Catelog2Vo>> stringListMap = getgetCatalog3GetDB();
            String jsonString = JSON.toJSONString(stringListMap);
            ops.set(GET_GETCATALOG3_KEY,jsonString,30, TimeUnit.MINUTES);
            return stringListMap;

        }
        Map<String, List<Catelog2Vo>> map = JSON.parseObject(json, new TypeReference<Map<String, List<Catelog2Vo>>>() {
        });
        return map;
    }

@Autowired
private RedissonClient redissonClient;

    public Map<String, List<Catelog2Vo>> getCatalog3ByRedisson() {
        //先从redis里面获取
        RLock lock = redissonClient.getLock("getCatalog3");
        lock.lock();
        Map<String, List<Catelog2Vo>> map =null;
        try {
           map = getgetCatalog3GetDB();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

        return map;
    }


    public Map<String, List<Catelog2Vo>> getgetCatalog3GetDB() {
        List<CategoryEntity> allList = this.list(null);
        List<CategoryEntity> category1 = getParent_cid(allList,0L);


        Map<String, List<Catelog2Vo>> map = category1.stream().collect(Collectors.toMap(s -> s.getCatId().toString(), v -> {
                    List<CategoryEntity> list2 = getParent_cid(allList,v.getCatId());

                    List<Catelog2Vo> collect = null;
                    if (CollectionUtil.isNotEmpty(list2)) {
                        collect = list2.stream().map(s -> {
                            Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, s.getCatId().toString(), s.getName());
                            List<CategoryEntity> list3 = getParent_cid(allList,s.getCatId());
                            if (CollectionUtil.isNotEmpty(list3)){
                                List<Catelog2Vo.Category3Vo> collect1 = list3.stream().map(s3 -> {
                                    return new Catelog2Vo.Category3Vo(s.getCatId().toString(), s3.getCatId().toString(), s3.getName());
                                }).collect(Collectors.toList());
                                catelog2Vo.setCatalog3List(collect1);
                            }
                            return catelog2Vo ;
                        }).collect(Collectors.toList());

                    }
                    return collect;
                }
        ));


        return map;
    }


    private   void getparentid(Long attrGroupId, List<Long> list) {
        list.add(attrGroupId);
        CategoryEntity categoryEntity = this.baseMapper.selectById(attrGroupId);
        if (categoryEntity.getParentCid() != 0) {
            getparentid(categoryEntity.getParentCid(), list);
        }
    }

    //递归查询所有菜单的子菜单
    private List<CategoryEntity> getChildren(CategoryEntity root, List<CategoryEntity> list) {
        List<CategoryEntity> collect = list.stream().filter(tow -> tow.getParentCid().equals(root.getCatId()))
                //子菜单下还有子菜单
                .map(categoryEntity -> {
                    categoryEntity.setChildren(getChildren(categoryEntity, list));
                    return categoryEntity;
                })
                .sorted((s1, s2) -> {
                    return (s1.getSort() == null ? 0 : s1.getSort()) - (s2.getSort() == null ? 0 : s2.getSort());
                })
                .collect(Collectors.toList());
        return collect;
    }

    private List<CategoryEntity> getParent_cid(List<CategoryEntity> allList ,Long  parentCid) {
        return   allList.stream().filter(s->s.getParentCid()==parentCid).collect(Collectors.toList());
    }

}
